package com.fjwt.gz.service.activity.coupon.acte004;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fjwt.gz.components.mq.websocket.server.MinProgramWsChannelServer;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.bo.ActivityAwardAndSettingBo;
import com.fjwt.gz.db.bo.ActivityUserTimesBO;
import com.fjwt.gz.db.dto.FansActivityDTO;
import com.fjwt.gz.db.entity.*;
import com.fjwt.gz.db.vo.ActivityAwardVO;
import com.fjwt.gz.service.activity.BaseActivityDTO;
import com.fjwt.gz.service.activity.BaseActivityService;
import com.fjwt.gz.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 用户扫码领券 扫码领券------
 */
@Slf4j
@Service
public class ACTE004Service extends BaseActivityService<Object> {

    private static String logPrefix = "【扫码领券】";

    @Autowired
    private ActivityAwardService activityAwardService;

    @Autowired
    private FansAwardService fansAwardService;

    @Autowired
    private QrcodeRecordService qrcodeRecordService;

    @Autowired
    private AgentAppService agentAppService;

    @Autowired
    private FansQrcodeService fansQrcodeService;

    @Autowired
    private ActivitySettingService activitySettingService;

    @Autowired
    private SendAwardService sendAwardService;

    @Autowired
    private AwardSettingService awardSettingService;

    @Autowired
    private MchInfoService mchInfoService;

    @Autowired
    private AgentInfoService agentInfoService;

    @Autowired
    private AgentEmployeeService agentEmployeeService;

    @Autowired
    private AwardAgentService awardAgentService;


    /**
     * 新建活动
     */
    @Override
    public void add(BaseActivityDTO activityDTO) {
        log.info("新增ACTE004的活动");
        super.add(activityDTO);
    }

    /**
     * 修改活动
     */
    @Override
    public void update(BaseActivityDTO activityDTO) {
        log.info("更新ACTE004的活动");
        super.update(activityDTO);
    }

    /**
     * 删除活动
     */
    @Override
    public void delete(Long activityId) {
        log.info("删除ACTE004的活动");
        super.delete(activityId);
    }

    /**
     * 活动详情--pc
     */
    @Override
    public BaseActivityDTO detail(Long activityId) {
        log.info("查看ACTE004的活动详情");
        return super.detail(activityId);
    }

    @Transactional
    public ActivityAwardVO takePartIn(FansActivityDTO fansActivityDTO) {
        log.info("进入{}", logPrefix);
        super.takePartIn(fansActivityDTO);
        String appId = fansActivityDTO.getAppId();
        Long fansId = fansActivityDTO.getFansId();
        Long activityId = fansActivityDTO.getActivityId();
        Long qrcodeRecordId = fansActivityDTO.getQrcodeRecordId();
        String qrcodeGetNumKey = "qrcode:qrcodeRecordNum:" + qrcodeRecordId;
        String qrcodeUserNumKey = "fansNum:" + fansId + ":qrcode:" + qrcodeRecordId;
        QrcodeRecordEntity recordEntity = qrcodeRecordService.getById(qrcodeRecordId);
        log.info("领券二维码信息:{}", JSON.toJSONString(recordEntity));
        AgentAppEntity agentAppEntity = agentAppService.getOne(AgentAppEntity.gw()
                .eq(AgentAppEntity::getAppId, appId)
                .eq(AgentAppEntity::getType, 1));
        if (Objects.isNull(recordEntity) || StringUtils.isEmpty(appId) || null == agentAppEntity) {
            throw new BizException("领取二维码已失效！");
        }
        Long payAuthId = activityEntity.getPayAuthId();

        // 检测用户参与限制条件
        JSONObject limitJson = activitySettingService.checkActivitySetting(fansEntity, appId, redisOutTime, activityEntity);

        List<ActivityAwardAndSettingBo> activityAwardList = awardSettingService.getActivityAwardList(activityId, redisOutTime);
        // 固定数量卡券领取
        if (1 == recordEntity.getType()) {
            // 二维码总领取数量
            Integer qrcodeGetNum = RedisUtil.getInterger(qrcodeGetNumKey);
            log.info("领券二维码qrcodeGetNumKey：{}，已领取总次数：{}", qrcodeGetNumKey, qrcodeGetNum);
            if (qrcodeGetNum == null) {
                qrcodeGetNum = recordEntity.getNumTotal();
                RedisUtil.setInteger(qrcodeGetNumKey, qrcodeGetNum);
                RedisUtil.expire(qrcodeGetNumKey, redisOutTime, TimeUnit.MILLISECONDS);
                log.info("领券二维码qrcodeGetNumKey：{}，已领取总次数：{}", qrcodeGetNumKey, qrcodeGetNum);
            } else if (0 >= qrcodeGetNum) {
                throw new BizException("领取已上限！");
            }
            // 用户领取数量
            Integer qrcodeUserNum = RedisUtil.getInterger(qrcodeUserNumKey);
            log.info("用户：{},领取:领券二维码qrcodeGetNumKey：{}，已领取次数：{}", fansId, qrcodeGetNumKey, qrcodeUserNum);
            if (qrcodeUserNum == null) {
                //查询用户的领取记录
                List<FansQrcodeEntity> list = fansQrcodeService.list(FansQrcodeEntity.gw()
                        .eq(FansQrcodeEntity::getQrcodeRecordId, qrcodeRecordId)
                        .eq(FansQrcodeEntity::getFansId, fansId)
                        .eq(FansQrcodeEntity::getAppId, appId));
                qrcodeUserNum = list.size();
            }
            if (qrcodeUserNum == 0) {
                FansQrcodeEntity entity = new FansQrcodeEntity();
                entity.setFansId(fansId);
                entity.setQrcodeRecordId(qrcodeRecordId);
                entity.setCreatedAt(new Date());
                entity.setAppId(appId);
                fansQrcodeService.getBaseMapper().insert(entity);
                // 二维码记录变更数据
                QrcodeRecordEntity dto = new QrcodeRecordEntity();
                dto.setQrcodeRecordId(recordEntity.getQrcodeRecordId());
                dto.setNumConsume(recordEntity.getNumConsume() + 1);
                boolean isUpdateSuccess = qrcodeRecordService.updateById(dto);
                if (!isUpdateSuccess) {
                    throw new BizException("活动太火爆了，请稍后再试!");
                }
                sendAward(appId, activityAwardList, recordEntity, fansActivityDTO, activityId, fansId, payAuthId);
                // 更新缓存数据
                RedisUtil.setInteger(qrcodeUserNumKey, 1);
                RedisUtil.expire(qrcodeUserNumKey, redisOutTime, TimeUnit.MILLISECONDS);
                RedisUtil.set(qrcodeGetNumKey, qrcodeGetNum - 1);
                log.info("用户fansId:{}第一次领取卡券,领取后卡券数量：{}", fansId, qrcodeGetNum - 1);
            } else if (qrcodeUserNum < recordEntity.getNumEveryone()) {
                FansQrcodeEntity entity = new FansQrcodeEntity();
                entity.setFansId(fansId);
                entity.setAppId(appId);
                entity.setQrcodeRecordId(qrcodeRecordId);
                entity.setCreatedAt(new Date());
                fansQrcodeService.getBaseMapper().insert(entity);
                // 二维码记录变更数据
                QrcodeRecordEntity dto = new QrcodeRecordEntity();
                dto.setQrcodeRecordId(recordEntity.getQrcodeRecordId());
                dto.setNumConsume(recordEntity.getNumConsume() + 1);
                boolean isUpdateSuccess = qrcodeRecordService.updateById(dto);
                if (!isUpdateSuccess) {
                    throw new BizException("活动太火爆了，请稍后再试!");
                }
                sendAward(appId, activityAwardList, recordEntity, fansActivityDTO, activityId, fansId, payAuthId);
                RedisUtil.setInteger(qrcodeUserNumKey, qrcodeUserNum + 1);
                RedisUtil.expire(qrcodeUserNumKey, redisOutTime, TimeUnit.MILLISECONDS);
                RedisUtil.set(qrcodeGetNumKey, qrcodeGetNum - 1);
                log.info("用户userId:{}领取后卡券数量：{}", fansId, qrcodeGetNum - 1);
            } else {
                throw new BizException("个人领取次数已达上限！");
            }
        } else {
            // 无上限领取卡券
            FansQrcodeEntity entity = new FansQrcodeEntity();
            entity.setFansId(fansId);
            entity.setQrcodeRecordId(qrcodeRecordId);
            entity.setCreatedAt(new Date());
            entity.setAppId(appId);
            fansQrcodeService.getBaseMapper().insert(entity);
            // 二维码记录变更数据
            QrcodeRecordEntity dto = new QrcodeRecordEntity();
            dto.setQrcodeRecordId(recordEntity.getQrcodeRecordId());
            dto.setNumConsume(recordEntity.getNumConsume() + 1);
            boolean isUpdateSuccess = qrcodeRecordService.updateById(dto);
            if (!isUpdateSuccess) {
                throw new BizException("活动太火爆了，请稍后再试!");
            }
            sendAward(appId, activityAwardList, recordEntity, fansActivityDTO, activityId, fansId, payAuthId);
        }

        //重新放置活动奖品配置缓存
        if (!activityAwardList.isEmpty()) {
            String activityAwardKey = String.format("%s%s:%s", Constants.REDIS_ACTIVITY.FILENAME, fansActivityDTO.getActivityId(), Constants.REDIS_ACTIVITY.AWARD);
            RedisUtil.set(activityAwardKey, activityAwardList, redisOutTime, TimeUnit.MILLISECONDS);
            log.info("活动奖品列表，修改奖品中的当前周期性领取次数数据，redisKey:{},redisValue:{},redisOutTime:{},TimeUnit:{}", activityAwardKey, JSONUtil.toJsonStr(activityAwardList), redisOutTime, "TimeUnit.MILLISECONDS");
        }

        //更新Redis中参与的次数
        ActivityUserTimesBO activityUserTimesBO = limitJson.getObject("activityUserTimesBO", ActivityUserTimesBO.class);
        if (ObjectUtils.isNotEmpty(activityUserTimesBO)){
            activitySettingService.updateRedisParticipateNum(limitJson.getString("currentTimesKey"), activityUserTimesBO, redisOutTime);
        }
        Boolean userJoinScoreValue = limitJson.getObject("userJoinScoreValue", Boolean.class);
        if (ObjectUtils.isNotEmpty(userJoinScoreValue)){
            RedisUtil.set(limitJson.getString("userJoinScoreKey"), userJoinScoreValue, redisOutTime, TimeUnit.MILLISECONDS);
        }
        return activityAwardService.toUserData(null);
    }

    public void sendAward(String appId, List<ActivityAwardAndSettingBo> activityAwardList, QrcodeRecordEntity recordEntity,
                          FansActivityDTO fansActivityDTO, Long activityId, Long fansId, Long payAuthId) {
        // 校验用户奖品限制
        Map<Long, JSONObject> awardUserTimesJsonMap = new HashMap<>();
        for (ActivityAwardAndSettingBo activityAwardAndSettingBo : activityAwardList) {
            JSONObject awardUserTimesJson = awardSettingService.AwardSettingRule(fansId, activityEntity.getAgentNo(), activityAwardAndSettingBo);
            if (ObjectUtils.isNotEmpty(awardUserTimesJson)) {
                awardUserTimesJsonMap.put(activityAwardAndSettingBo.getAwardId(), awardUserTimesJson);
            }
        }

        for (ActivityAwardAndSettingBo awardAndSettingBo : activityAwardList) {
            AwardAgentEntity awardAgentEntity = awardAgentService.lambdaQuery()
                    .eq(AwardAgentEntity::getAwardId, awardAndSettingBo.getAwardId())
                    .eq(AwardAgentEntity::getAgentNo, activityEntity.getAgentNo()).one();
            if (awardAgentEntity != null){
                if (awardAgentEntity.getNum() <= (awardAgentEntity.getNumAllocation() + awardAgentEntity.getNumConsume())) {
                    throw new BizException("奖品数量不足！");
                }
                awardAgentEntity.setNumConsume(awardAgentEntity.getNumConsume() + 1);
                awardAgentService.updateById(awardAgentEntity);
            }
            log.info("活动奖品详细信息:{}", JSONUtil.toJsonStr(awardAndSettingBo));
            awardAndSettingBo.setRemark("扫码领券！");
            Long fansAwardId = sendAwardService.sendCouponOrGoods(fansId, appId,  awardAndSettingBo, payAuthId,
                    null, true, fansActivityDTO.getExtJson());

            JSONObject awardUserTimesJson = awardUserTimesJsonMap.get(awardAndSettingBo.getAwardId());
            awardSettingService.updateAwardLimitCache(awardUserTimesJson, redisOutTime);

            if(null != fansAwardId){
                log.info("设置的二维码参数信息：{}", JSONObject.toJSONString(recordEntity));
                if(0 == recordEntity.getTagType()){
                    log.info("进入商户扫码领券");
                    FansAwardEntity awardEntity = new FansAwardEntity();
                    awardEntity.setSendMchNo(recordEntity.getTagInfo());
                    MchInfoEntity mchInfo = mchInfoService.getById(recordEntity.getTagInfo());
                    awardEntity.setSendAgentNo(mchInfo.getAgentNo());
                    awardEntity.setSendAgentNo1(mchInfo.getAgentNo1());
                    awardEntity.setSendAgentNo2(mchInfo.getAgentNo2());
                    awardEntity.setSendAgentNo3(mchInfo.getAgentNo3());
                    awardEntity.setSendAgentNo4(mchInfo.getAgentNo4());
                    awardEntity.setSendMchNo(mchInfo.getMchNo());
                    awardEntity.setFansAwardId(fansAwardId);
                    fansAwardService.updateById(awardEntity);
                }else if(1 ==  recordEntity.getTagType()){
                    log.info("进入机构扫描领券");
                    AgentInfoEntity agentInfo = agentInfoService.getAgentInfo(recordEntity.getTagInfo());
                    if(null != agentInfo){
                        FansAwardEntity awardEntity = new FansAwardEntity();
                        awardEntity.setSendAgentNo(agentInfo.getAgentNo());
                        awardEntity.setSendAgentNo1(agentInfo.getAgentNo1());
                        awardEntity.setSendAgentNo2(agentInfo.getAgentNo2());
                        awardEntity.setSendAgentNo3(agentInfo.getAgentNo3());
                        awardEntity.setSendAgentNo4(agentInfo.getAgentNo4());
                        awardEntity.setFansAwardId(fansAwardId);
                        fansAwardService.updateById(awardEntity);
                    }
                }else if(2 == recordEntity.getTagType()){
                    log.info("进入客户经理扫描领券");
                    AgentEmployeeEntity employeeEntity = agentEmployeeService.getById(recordEntity.getTagInfo());
                    AgentInfoEntity agentInfo = agentInfoService.getById(employeeEntity.getAgentNo());
                    if(null != agentInfo){
                        FansAwardEntity awardEntity = new FansAwardEntity();
                        awardEntity.setSendAgentNo(agentInfo.getAgentNo());
                        awardEntity.setSendAgentNo1(agentInfo.getAgentNo1());
                        awardEntity.setSendAgentNo2(agentInfo.getAgentNo2());
                        awardEntity.setSendAgentNo3(agentInfo.getAgentNo3());
                        awardEntity.setSendAgentNo4(agentInfo.getAgentNo4());
                        awardEntity.setFansAwardId(fansAwardId);
                        fansAwardService.updateById(awardEntity);
                    }
                }
//                wsChannelServer.convertAndSend(String.valueOf(fansId), appId, "扫码领券", "领取成功！");
//            }else {
//                wsChannelServer.convertAndSend(String.valueOf(fansId), appId, "扫码领券", "领取失败！");
            }
        }
    }

}
